home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap18 / EmfView / EmfView.c next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  14.2 KB  |  428 lines

  1. /*----------------------------------------
  2.    EMFVIEW.C -- View Enhanced Metafiles
  3.                 (c) Charles Petzold, 1998
  4.   ----------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <commdlg.h>
  8. #include "resource.h"
  9.  
  10. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  11.  
  12. TCHAR szAppName[] = TEXT ("EmfView") ;
  13.  
  14. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  15.                     PSTR szCmdLine, int iCmdShow)
  16. {
  17.      HACCEL   hAccel ;
  18.      HWND     hwnd ;
  19.      MSG      msg ;
  20.      WNDCLASS wndclass ;
  21.  
  22.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  23.      wndclass.lpfnWndProc   = WndProc ;
  24.      wndclass.cbClsExtra    = 0 ;
  25.      wndclass.cbWndExtra    = 0 ;
  26.      wndclass.hInstance     = hInstance ;
  27.      wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  28.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  29.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  30.      wndclass.lpszMenuName  = szAppName ;
  31.      wndclass.lpszClassName = szAppName ;
  32.  
  33.      if (!RegisterClass (&wndclass))
  34.      {
  35.           MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
  36.                       szAppName, MB_ICONERROR) ;
  37.           return 0 ;
  38.      }
  39.  
  40.      hwnd = CreateWindow (szAppName, TEXT ("Enhanced Metafile Viewer"),
  41.                           WS_OVERLAPPEDWINDOW,
  42.                           CW_USEDEFAULT, CW_USEDEFAULT,
  43.                           CW_USEDEFAULT, CW_USEDEFAULT, 
  44.                           NULL, NULL, hInstance, NULL) ;
  45.  
  46.      ShowWindow (hwnd, iCmdShow) ;
  47.      UpdateWindow (hwnd) ;
  48.  
  49.      hAccel = LoadAccelerators (hInstance, szAppName) ;
  50.  
  51.      while (GetMessage (&msg, NULL, 0, 0))
  52.      {
  53.           if (!TranslateAccelerator (hwnd, hAccel, &msg))
  54.           {
  55.                TranslateMessage (&msg) ;
  56.                DispatchMessage (&msg) ;
  57.           }
  58.      }
  59.      return msg.wParam ;
  60. }
  61.  
  62. HPALETTE CreatePaletteFromMetaFile (HENHMETAFILE hemf)
  63. {
  64.      HPALETTE     hPalette ;
  65.      int          iNum ;
  66.      LOGPALETTE * plp ;
  67.  
  68.      if (!hemf)
  69.           return NULL ;
  70.  
  71.      if (0 == (iNum = GetEnhMetaFilePaletteEntries (hemf, 0, NULL)))
  72.           return NULL ;
  73.  
  74.      plp = malloc (sizeof (LOGPALETTE) + (iNum - 1) * sizeof (PALETTEENTRY)) ;
  75.  
  76.      plp->palVersion    = 0x0300 ;
  77.      plp->palNumEntries = iNum ;
  78.  
  79.      GetEnhMetaFilePaletteEntries (hemf, iNum, plp->palPalEntry) ;
  80.      
  81.      hPalette = CreatePalette (plp) ;
  82.  
  83.      free (plp) ;
  84.  
  85.      return hPalette ;
  86. }
  87.  
  88. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  89. {
  90.      static DOCINFO      di = { sizeof (DOCINFO), TEXT ("EmfView: Printing") } ;
  91.      static HENHMETAFILE hemf ;
  92.      static OPENFILENAME ofn ;
  93.      static PRINTDLG     printdlg = { sizeof (PRINTDLG) } ;
  94.      static TCHAR        szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
  95.      static TCHAR        szFilter[] = 
  96.                                TEXT ("Enhanced Metafiles (*.EMF)\0*.emf\0")
  97.                                TEXT ("All Files (*.*)\0*.*\0\0") ;
  98.      BOOL                bSuccess ;
  99.      ENHMETAHEADER       header ;
  100.      HDC                 hdc, hdcPrn ;
  101.      HENHMETAFILE        hemfCopy ;
  102.      HMENU               hMenu ;
  103.      HPALETTE            hPalette ;
  104.      int                 i, iLength, iEnable ;
  105.      PAINTSTRUCT         ps ;
  106.      RECT                rect ;
  107.      PTSTR               pBuffer ;
  108.  
  109.      switch (message)
  110.      {
  111.      case WM_CREATE:
  112.                // Initialize OPENFILENAME structure
  113.      
  114.           ofn.lStructSize       = sizeof (OPENFILENAME) ;
  115.           ofn.hwndOwner         = hwnd ;
  116.           ofn.hInstance         = NULL ;
  117.           ofn.lpstrFilter       = szFilter ;
  118.           ofn.lpstrCustomFilter = NULL ;
  119.           ofn.nMaxCustFilter    = 0 ;
  120.           ofn.nFilterIndex      = 0 ;
  121.           ofn.lpstrFile         = szFileName ;
  122.           ofn.nMaxFile          = MAX_PATH ;
  123.           ofn.lpstrFileTitle    = szTitleName ;
  124.           ofn.nMaxFileTitle     = MAX_PATH ;
  125.           ofn.lpstrInitialDir   = NULL ;
  126.           ofn.lpstrTitle        = NULL ;
  127.           ofn.Flags             = 0 ;   
  128.           ofn.nFileOffset       = 0 ;
  129.           ofn.nFileExtension    = 0 ;
  130.           ofn.lpstrDefExt       = TEXT ("emf") ;
  131.           ofn.lCustData         = 0 ;
  132.           ofn.lpfnHook          = NULL ;
  133.           ofn.lpTemplateName    = NULL ;
  134.           return 0 ;
  135.  
  136.      case WM_INITMENUPOPUP:
  137.           hMenu = GetMenu (hwnd) ;
  138.  
  139.           iEnable = hemf ? MF_ENABLED : MF_GRAYED ;
  140.  
  141.           EnableMenuItem (hMenu, IDM_FILE_SAVE_AS,    iEnable) ;
  142.           EnableMenuItem (hMenu, IDM_FILE_PRINT,      iEnable) ;
  143.           EnableMenuItem (hMenu, IDM_FILE_PROPERTIES, iEnable) ;
  144.           EnableMenuItem (hMenu, IDM_EDIT_CUT,        iEnable) ;
  145.           EnableMenuItem (hMenu, IDM_EDIT_COPY,       iEnable) ;
  146.           EnableMenuItem (hMenu, IDM_EDIT_DELETE,     iEnable) ;
  147.  
  148.           EnableMenuItem (hMenu, IDM_EDIT_PASTE,
  149.                IsClipboardFormatAvailable (CF_ENHMETAFILE) ?
  150.                     MF_ENABLED : MF_GRAYED) ;
  151.           return 0 ;
  152.  
  153.      case WM_COMMAND:
  154.           switch (LOWORD (wParam))
  155.           {
  156.           case IDM_FILE_OPEN:
  157.                     // Show the File Open dialog box
  158.  
  159.                ofn.Flags = 0 ;
  160.      
  161.                if (!GetOpenFileName (&ofn))
  162.                     return 0 ;
  163.                
  164.                     // If there's an existing EMF, get rid of it.
  165.  
  166.                if (hemf)
  167.                {
  168.                     DeleteEnhMetaFile (hemf) ;
  169.                     hemf = NULL ;
  170.                }
  171.                     // Load the EMF into memory
  172.  
  173.                SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
  174.                ShowCursor (TRUE) ;
  175.  
  176.                hemf = GetEnhMetaFile (szFileName) ;
  177.  
  178.                ShowCursor (FALSE) ;
  179.                SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
  180.  
  181.                     // Invalidate the client area for later update
  182.  
  183.                InvalidateRect (hwnd, NULL, TRUE) ;
  184.  
  185.                if (hemf == NULL)
  186.                {
  187.                     MessageBox (hwnd, TEXT ("Cannot load metafile"), 
  188.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  189.                }
  190.                return 0 ;
  191.  
  192.           case IDM_FILE_SAVE_AS:
  193.                if (!hemf)
  194.                     return 0 ;
  195.  
  196.                     // Show the File Save dialog box
  197.  
  198.                ofn.Flags = OFN_OVERWRITEPROMPT ;
  199.      
  200.                if (!GetSaveFileName (&ofn))
  201.                     return 0 ;
  202.                
  203.                     // Save the EMF to disk file
  204.  
  205.                SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
  206.                ShowCursor (TRUE) ;
  207.  
  208.                hemfCopy = CopyEnhMetaFile (hemf, szFileName) ;
  209.  
  210.                ShowCursor (FALSE) ;
  211.                SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
  212.  
  213.                if (hemfCopy)
  214.                {
  215.                     DeleteEnhMetaFile (hemf) ;
  216.                     hemf = hemfCopy ;
  217.                }
  218.                else
  219.                     MessageBox (hwnd, TEXT ("Cannot save metafile"), 
  220.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  221.                return 0 ;
  222.  
  223.           case IDM_FILE_PRINT:
  224.                     // Show the Print dialog box and get printer DC
  225.     
  226.               printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ;
  227.  
  228.               if (!PrintDlg (&printdlg))
  229.                   return 0 ;
  230.                
  231.                if (NULL == (hdcPrn = printdlg.hDC)) 
  232.                {
  233.                     MessageBox (hwnd, TEXT ("Cannot obtain printer DC"),
  234.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  235.                     return 0 ;
  236.                }
  237.                     // Get size of printable area of page
  238.  
  239.                rect.left   = 0 ;
  240.                rect.right  = GetDeviceCaps (hdcPrn, HORZRES) ;
  241.                rect.top    = 0 ;
  242.                rect.bottom = GetDeviceCaps (hdcPrn, VERTRES) ;
  243.  
  244.                bSuccess = FALSE ;
  245.  
  246.                     // Play the EMF to the printer
  247.  
  248.                SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
  249.                ShowCursor (TRUE) ;
  250.  
  251.                if ((StartDoc (hdcPrn, &di) > 0) && (StartPage (hdcPrn) > 0))
  252.                {
  253.                     PlayEnhMetaFile (hdcPrn, hemf, &rect) ;
  254.                     
  255.                     if (EndPage (hdcPrn) > 0)
  256.                     {
  257.                          bSuccess = TRUE ;
  258.                          EndDoc (hdcPrn) ;
  259.                     }
  260.                }
  261.                ShowCursor (FALSE) ;
  262.                SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
  263.  
  264.                DeleteDC (hdcPrn) ;
  265.  
  266.                if (!bSuccess)
  267.                     MessageBox (hwnd, TEXT ("Could not print metafile"),
  268.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  269.                return 0 ;
  270.  
  271.           case IDM_FILE_PROPERTIES:
  272.                if (!hemf)
  273.                     return 0 ;
  274.  
  275.                iLength = GetEnhMetaFileDescription (hemf, 0, NULL) ;
  276.                pBuffer = malloc ((iLength + 256) * sizeof (TCHAR)) ;
  277.  
  278.                GetEnhMetaFileHeader (hemf, sizeof (ENHMETAHEADER), &header) ;
  279.  
  280.                     // Format header file information 
  281.  
  282.                i  = wsprintf (pBuffer, 
  283.                               TEXT ("Bounds = (%i, %i) to (%i, %i) pixels\n"),
  284.                               header.rclBounds.left, header.rclBounds.top,
  285.                               header.rclBounds.right, header.rclBounds.bottom) ;
  286.  
  287.                i += wsprintf (pBuffer + i, 
  288.                               TEXT ("Frame = (%i, %i) to (%i, %i) mms\n"),
  289.                               header.rclFrame.left, header.rclFrame.top,
  290.                               header.rclFrame.right, header.rclFrame.bottom) ;
  291.  
  292.                i += wsprintf (pBuffer + i,
  293.                               TEXT ("Resolution = (%i, %i) pixels")
  294.                               TEXT (" = (%i, %i) mms\n"),
  295.                               header.szlDevice.cx, header.szlDevice.cy,
  296.                               header.szlMillimeters.cx, 
  297.                               header.szlMillimeters.cy) ;
  298.  
  299.                i += wsprintf (pBuffer + i,
  300.                               TEXT ("Size = %i, Records = %i, ")
  301.                               TEXT ("Handles = %i, Palette entries = %i\n"),
  302.                               header.nBytes, header.nRecords,
  303.                               header.nHandles, header.nPalEntries) ;
  304.  
  305.                     // Include the metafile description, if present
  306.  
  307.                if (iLength)
  308.                {
  309.                     i += wsprintf (pBuffer + i, TEXT ("Description = ")) ;
  310.                     GetEnhMetaFileDescription (hemf, iLength, pBuffer + i) ;
  311.                     pBuffer [lstrlen (pBuffer)] = '\t' ;
  312.                }
  313.  
  314.                MessageBox (hwnd, pBuffer, TEXT ("Metafile Properties"), MB_OK) ;
  315.                free (pBuffer) ;                              
  316.                return 0 ;
  317.  
  318.           case IDM_EDIT_COPY:
  319.           case IDM_EDIT_CUT:
  320.                if (!hemf)
  321.                     return 0 ;
  322.  
  323.                     // Transfer metafile copy to the clipboard
  324.  
  325.                hemfCopy = CopyEnhMetaFile (hemf, NULL) ;
  326.  
  327.                OpenClipboard (hwnd) ;
  328.                EmptyClipboard () ;
  329.                SetClipboardData (CF_ENHMETAFILE, hemfCopy) ;
  330.                CloseClipboard () ;
  331.  
  332.                if (LOWORD (wParam) == IDM_EDIT_COPY)
  333.                     return 0 ;
  334.                                         // fall through if IDM_EDIT_CUT 
  335.           case IDM_EDIT_DELETE:
  336.                if (hemf)
  337.                {
  338.                     DeleteEnhMetaFile (hemf) ;
  339.                     hemf = NULL ;
  340.                     InvalidateRect (hwnd, NULL, TRUE) ;
  341.                }
  342.                return 0 ;
  343.  
  344.           case IDM_EDIT_PASTE:
  345.                OpenClipboard (hwnd) ;
  346.                hemfCopy = GetClipboardData (CF_ENHMETAFILE) ;
  347.                CloseClipboard () ;
  348.  
  349.                if (hemfCopy && hemf)
  350.                {
  351.                     DeleteEnhMetaFile (hemf) ;
  352.                     hemf = NULL ;
  353.                }
  354.  
  355.                hemf = CopyEnhMetaFile (hemfCopy, NULL) ;
  356.                InvalidateRect (hwnd, NULL, TRUE) ;
  357.                return 0 ;
  358.  
  359.           case IDM_APP_ABOUT:
  360.                MessageBox (hwnd, TEXT ("Enhanced Metafile Viewer\n")
  361.                                  TEXT ("(c) Charles Petzold, 1998"),
  362.                            szAppName, MB_OK) ;
  363.                return 0 ;
  364.  
  365.           case IDM_APP_EXIT:
  366.                SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
  367.                return 0 ;
  368.           }
  369.           break ;
  370.          
  371.      case WM_PAINT:
  372.           hdc = BeginPaint (hwnd, &ps) ;
  373.  
  374.           if (hemf)
  375.           {
  376.                if (hPalette = CreatePaletteFromMetaFile (hemf))
  377.                {
  378.                     SelectPalette (hdc, hPalette, FALSE) ;
  379.                     RealizePalette (hdc) ;
  380.                }
  381.                GetClientRect (hwnd, &rect) ;
  382.                PlayEnhMetaFile (hdc, hemf, &rect) ;
  383.  
  384.                if (hPalette)
  385.                     DeleteObject (hPalette) ;
  386.           }
  387.           EndPaint (hwnd, &ps) ;
  388.           return 0 ;
  389.  
  390.      case WM_QUERYNEWPALETTE:
  391.           if (!hemf || !(hPalette = CreatePaletteFromMetaFile (hemf)))
  392.                return FALSE ;
  393.  
  394.           hdc = GetDC (hwnd) ;
  395.           SelectPalette (hdc, hPalette, FALSE) ;
  396.           RealizePalette (hdc) ;
  397.           InvalidateRect (hwnd, NULL, FALSE) ;
  398.  
  399.           DeleteObject (hPalette) ;
  400.           ReleaseDC (hwnd, hdc) ;
  401.           return TRUE ;
  402.  
  403.      case WM_PALETTECHANGED:
  404.           if ((HWND) wParam == hwnd)
  405.                break ;
  406.  
  407.           if (!hemf || !(hPalette = CreatePaletteFromMetaFile (hemf)))
  408.                break ;
  409.  
  410.           hdc = GetDC (hwnd) ;
  411.           SelectPalette (hdc, hPalette, FALSE) ;
  412.           RealizePalette (hdc) ;
  413.           UpdateColors (hdc) ;
  414.  
  415.           DeleteObject (hPalette) ;
  416.           ReleaseDC (hwnd, hdc) ;
  417.           break ;
  418.           
  419.      case WM_DESTROY:
  420.           if (hemf)
  421.                DeleteEnhMetaFile (hemf) ;
  422.  
  423.           PostQuitMessage (0) ;
  424.           return 0 ;
  425.      }
  426.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  427. }
  428.